<template>
  <div class="PropContComponent">
    <ul class="staticListGroup">
      <li class="listGroupItem">
        <div class="itemContent">
          <label> <input type="checkbox" v-model="stageProps.offsetCenter" />原点移到画面中央</label>
        </div>
      </li>
    </ul>
    <div class="label">
      父元素<span class="info">(Stage-style)</span>:
    </div>
    <ul class="staticListGroup">
      <li class="listGroupItem">
        <div class="itemContent">
          <Slider label="perspective" v-model="stageProps.perspective" :min="0" :max="1000" suffix="px" />
        </div>
      </li>
      <li class="listGroupItem">
        <div class="itemContent">
          <label><input type="checkbox" v-model="stageProps.preserve" />tansform-style: preserve-3d</label>
        </div>
      </li>
      <li class="listGroupItem">
        <div class="itemContent">
          <div>perspective-origin:</div>
          <Slider label="X" v-model="stageProps.perspectiveOriginX" :min="-20" :max="120" :suffix="perspectiveOriginXSuffix" />
          <Slider label="Y" v-model="stageProps.perspectiveOriginY" :min="-20" :max="120" :suffix="perspectiveOriginYSuffix" />
        </div>
      </li>
    </ul>
    <div class="label">中心轴<span class="info">(Transform-origin)</span>:</div>
    <ul class="staticListGroup" v-if="cardProps.transformOriginX !== undefined">
      <li class="listGroupItem">
        <div class="itemContent">
          <Slider label="X" v-model="cardProps.transformOriginX" :min="0" :max="100" :suffix="transformOriginXSuffix" />
          <Slider label="Y" v-model="cardProps.transformOriginY" :min="0" :max="100" :suffix="transformOriginYSuffix" />
        </div>
      </li>
    </ul>
    <div class="label">子元素<span class="info">(Transform)</span>:</div>
    <!-- tag="transition-group" -->
    <draggable
      class="draggableListGroup"
      :component-data="{
        name: !state.drag ? 'flip-list' : null,
        tag: 'ul',
        type: 'transition-group',
      }"
      v-model="list"
      v-bind="state.dragOptions"
      @start="state.drag=true"
      @end="state.drag=false"
      item-key="id">
      <template #item="{ element, index }">
        <li class="listGroupItem">
          <div class="itemContent">
            <Slider
              :index="index"
              :label="names[element.key]"
              :min="ranges[element.key][0]"
              :max="ranges[element.key][1]"
              :suffix="units[element.key]"
              v-model="element.value" />
          </div>
        </li>
      </template>
    </draggable>
  </div>
</template>
<script lang="ts">
import { TransformPropKey, TransformProp } from "@/types/CardProps";
import { computed, defineComponent, PropType, reactive, ref } from "vue";
import draggable from "vuedraggable";
import Slider from "./Slider.vue";
import { transformPropName } from "@/logics/transformPropName";
import { transformPropUnit } from "@/logics/transformPropUnit";

type State = {
  drag: boolean;
  dragOptions: {
    animation: number;
    group: string;
    disabled: boolean;
    ghostClass: string;
  };
};

const PROPRANGES: { [k in TransformPropKey]: number[] } = {
  x: [-500, 500],
  y: [-500, 500],
  z: [-500, 500],
  rx: [-360, 360],
  ry: [-360, 360],
  rz: [-360, 360]
};

export default defineComponent({
  components: {
    draggable,
    Slider
  },
  props: {
    transforms: { default: () => [], type: Array as PropType<TransformProp[]> },
    transformOriginX: { type: Number },
    transformOriginY: { type: Number },
    offsetCenter: { default: true, type: Boolean },
    perspective: { default: 0, type: Number },
    preserve: { default: false, type: Boolean },
    perspectiveOriginX: { default: 0, type: Number },
    perspectiveOriginY: { default: 0, type: Number },
  },
  emits: [
    "update:transforms",
    "update:transformOriginX",
    "update:transformOriginY",
    "update:perspective",
    "update:preserve",
    "update:perspectiveOriginX",
    "update:perspectiveOriginY",
    "update:offsetCenter"
  ],
  setup(props, ctx) {
    const state = reactive < State > ({
      drag: false,
      dragOptions: {
        animation: 200,
        group: "description",
        disabled: false,
        ghostClass: "ghost"
      }
    });

    const list = computed({
      get: () => props.transforms ?? [],
      set: (l) => {
        ctx.emit("update:transforms", l);
        console.log("update:transforms", l);
      }
    });

    const stageProps = reactive({
      perspective: computed({
        get: () => props.perspective,
        set: (v) => ctx.emit("update:perspective", v)
      }),
      preserve: computed({
        get: () => props.preserve,
        set: (v) => ctx.emit("update:preserve", v)
      }),
      perspectiveOriginX: computed({
        get: () => props.perspectiveOriginX,
        set: (v) => ctx.emit("update:perspectiveOriginX", v)
      }),
      perspectiveOriginY: computed({
        get: () => props.perspectiveOriginY,
        set: (v) => ctx.emit("update:perspectiveOriginY", v)
      }),
      offsetCenter: computed({
        get: () => props.offsetCenter,
        set: (v) => ctx.emit("update:offsetCenter", v)
      })
    });

    const cardProps = reactive({
      transformOriginX: computed({
        get: () => props.transformOriginX,
        set: (v) => ctx.emit("update:transformOriginX", v)
      }),
      transformOriginY: computed({
        get: () => props.transformOriginY,
        set: (v) => ctx.emit("update:transformOriginY", v)
      })
    });

    const ranges = ref(PROPRANGES);
    const names = ref(transformPropName);
    const units = ref(transformPropUnit);

    const originToSuffixStr = (o: number | undefined, isX: boolean) => {
      if (o == undefined) return "";
      if (o === 0) return "% = " + (isX ? "left" : "top");
      if (o === 50) return "% = center";
      if (o === 100) return "% = " + (isX ? "right" : "bottom");
      return "%";
    };
    
    const transformOriginXSuffix = computed(() =>
      originToSuffixStr(props.transformOriginX, true)
    );
    
    const transformOriginYSuffix = computed(() =>
      originToSuffixStr(props.transformOriginY, false)
    );
    
    const perspectiveOriginXSuffix = computed(() =>
      originToSuffixStr(props.perspectiveOriginX, true)
    );
    
    const perspectiveOriginYSuffix = computed(() =>
      originToSuffixStr(props.perspectiveOriginY, false)
    );

    return {
      state,
      list,
      ranges,
      stageProps,
      cardProps,
      names,
      units,
      transformOriginXSuffix,
      transformOriginYSuffix,
      perspectiveOriginXSuffix,
      perspectiveOriginYSuffix
    };
  }
});
</script>
<style lang="scss" scoped>
.PropContComponent {
  .label {
    font-family: Arial, 楷体, 'Microsoft Yahei', sans-serif;
    font-weight: bolder;

    .info {
      font-size: 12px;
    }
  }

  .staticListGroup {
    margin: 0 0 2px 0;
    padding: 0;
    border-bottom: 2px solid #AAAAAA;

    .listGroupItem+.listGroupItem {
      border-top: 1px solid #AAAAAA;
    }
  }

  .draggableListGroup {
    min-height: 20px;
    margin: 0;
    padding: 0;

    .flip-list-move {
      transition: transform 0.5s;
    }

    .no-move {
      transition: transform 0s;
    }

    .ghost {
      opacity: 0.5;
      background: #C8EBFB;
    }

    .listGroupItem {
      margin-bottom: 1px;
      border-radius: 4px;
      border: 1px solid darkgray;
      cursor: move;

      &::before {
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        width: 10px;
        height: 100%;
        border-radius: 2px 0 0 2px;
        background-color: darkgray;
      }
    }
  }

  .listGroupItem {
    list-style: none;
    padding-left: 12px;
    background-color: #FFFFFF;
    position: relative;

    .itemContent {
      padding: 4px 8px;
    }
  }
}
</style>